#pragma once
#include<iostream>
#include <sys/epoll.h>
#include"log.hpp"
static const int gsize = 128;
class Multiplex
{
public:
    virtual bool AddEvent(int fd,uint32_t events)=0;
    virtual bool ModEvent(int fd,uint32_t events)=0;
    virtual bool DelEvent(int fd)=0;
    virtual int Wait(struct epoll_event revs[],int num,int timeout)=0;
};
class Epoller:public Multiplex
{
private:
    bool ModEventHandler(int fd,uint32_t events,int oper)
    {
        struct epoll_event ev;
        ev.events = events;
        ev.data.fd =fd;
        int n =epoll_ctl(_epfd,oper,fd,&ev);
         if (n < 0)
        {
            LOG(ERROR, "epoll_ctl %d events is %s failed\n", fd, EventsToString(events).c_str());
            return false;
        }

        LOG(INFO, "epoll_ctl %d events is %s success\n", fd, EventsToString(events).c_str());
        return true;
    }

public:
    Epoller()
    {
        _epfd = epoll_create(gsize);
        if(_epfd<0)
        {
            LOG(ERROR,"epoll create err\n");
            exit(2);
        }
        LOG(ERROR,"epoll create success\n");
    }
    virtual bool AddEvent(int fd,uint32_t events) override
    {
        return ModEventHandler(fd,events,EPOLL_CTL_ADD);
    }
    virtual bool ModEvent(int fd,uint32_t events) override
    {
        return ModEventHandler(fd,events,EPOLL_CTL_MOD);
    }
    virtual bool DelEvent(int fd)override
    {
        return epoll_ctl(_epfd,EPOLL_CTL_DEL,fd,nullptr);
    }
    virtual int Wait(struct epoll_event revs[],int num,int timeout)override
    {
        return epoll_wait(_epfd,revs,num,timeout);
    }
    const std::string EventsToString(uint32_t events)
    {
        std::string eventstr;
        if (events & EPOLLIN)
            eventstr = "EPOLLIN";
        if (events & EPOLLOUT)
            eventstr += "|EPOLLOUT";
        if (events & EPOLLET)
            eventstr += "|EPOLLET";
        return eventstr;
    }
private:
    int _epfd;
};
